/**
 * Copyright (C), 2015-2019, XXX有限公司
 * FileName: ActivityTurntableDrawProxy
 * Author:   zhouheng
 * Date:     2019/4/14 21:21
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.activity.services.processor;

import com.activity.dal.entitys.ActDrawAward;
import com.activity.dal.entitys.ActDrawAwardItem;
import com.activity.dal.entitys.ActDrawRecord;
import com.activity.dal.persistence.ActDrawAwardMapper;
import com.activity.services.processor.constants.DrawContants;
import com.activity.services.processor.exception.UnRewardException;
import com.activity.services.processor.reward.JdCardRewardProcessor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author zhouheng
 * @create 2019/4/14
 * @since 1.0.0
 */
@Slf4j
@Service("activityTurntableDrawProxy")
public class ActivityTurntableDrawProxy implements ApplicationContextAware {

    // 放大倍数
    private static final int mulriple = 10000;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    ActDrawAwardMapper actDrawAwardMapper;

    /**
     * 针对不同奖品类型的处理器
     */
    Map<Integer, RewardProcessor> rewardProcessorMap = new ConcurrentHashMap<Integer, RewardProcessor>();

    /**
     * @description: 抽奖业务
     * @date: 2019/4/14 21:25
     * @author:zhouheng
     */
    public void doDrawForProxy(ActivityDrawContext activityDrawContext) {
        //TODO 检查当前用户剩余抽奖次数

        try {
            List<ActDrawAwardItem> awardItems = (List<ActDrawAwardItem>) redisTemplate.opsForValue().get(DrawContants.DRAW_ITEM);
            ActDrawAwardItem item = doPlay(awardItems);
            ActDrawAward actDrawAward = actDrawAwardMapper.queryAwardById(item.getAwardId());
            activityDrawContext.setActDrawAwardItem(item);
            rewardProcessorMap.get(actDrawAward.getAwardType()).doReword(activityDrawContext);
        }catch(UnRewardException e){
            log.info("未抽到奖品或者出现异常的情况下");
        }finally {
            log.info("ActivityTurntableDrawProxy.doDrawForProxy->{}",activityDrawContext);
        }

    }

    /**
     * @description: 抽奖
     * @date: 2019/4/14 21:34
     * @author:zhouheng
     */
    private ActDrawAwardItem doPlay(List<ActDrawAwardItem> awardItems) {
        Map<Integer, Integer[]> map = new HashMap<Integer, Integer[]>();
        int lastScope = 0;
        Collections.shuffle(awardItems);

        for (ActDrawAwardItem item : awardItems){
            int currentScope = lastScope + new BigDecimal(item.getProbability().floatValue())
                    .multiply(new BigDecimal(mulriple)).intValue();
            map.put(item.getId(), new Integer[]{lastScope,currentScope});
            lastScope = currentScope;
        }

        // 随机生成随机数
        final int luckyNumber = new Random().nextInt(mulriple);
        int luckyPrizeId = 0;

        for (Map.Entry<Integer,Integer[]> entry : map.entrySet()){
            if (entry.getValue()[0] <= luckyNumber && entry.getValue()[1] >= luckyNumber){
                luckyPrizeId = entry.getKey();
                break;
            }
        }

        ActDrawAwardItem awardItem = null;
        for (ActDrawAwardItem item : awardItems) {
            if (item.getId().intValue() == luckyPrizeId) {
                awardItem = item;
                break;
            }
        }

        return awardItem;
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        rewardProcessorMap.put(DrawContants.AWARD_TYPE_ENUM.JD_CARD.getValue(), (RewardProcessor)applicationContext.getBean("jdCardRewardProcessor"));
        rewardProcessorMap.put(DrawContants.AWARD_TYPE_ENUM.FINANCE.getValue(),(RewardProcessor) applicationContext.getBean("financeRewardProcessor"));
        rewardProcessorMap.put(DrawContants.AWARD_TYPE_ENUM.NONE.getValue(),(RewardProcessor) applicationContext.getBean("noneRewardProcessor"));
    }
}